/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package umis2.controladorcentral;

import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import umis2.nivel.Nivel;
import umis2.nivel.Personaje;
import umis2.nivel.Plataforma;
import umis2.nivel.Relacionable;
import umis2.vista.Canvas;
import umis2.vista.Vista;

// Tal vez sea Singleton porque solo hay una copia en cada maquina virtual

// Usar properties para la relacion objetos nivel y urls, y cargarlos al iniciar la aplicacion

/**
 * Sabe qué imagen le corresponde a que parte del dominio. Para obtener la imagen utiliza
 * creador imagen.
 * El transformador crea Formas con las imagenes a pintar
 * @author Jonatan Elias
 */
public class Transformador {
    private HashMap<String, Image> imagenes;
    private List<Forma> formas;
    private int margen;
    public static int ALTO=60;
    public static int ANCHO=80;
    public static double PARALAJE = 4;
    public LinkedList<Forma> fondosL;
    private static Transformador INSTANCE = new Transformador();

    private Transformador() {
        this.formas = new LinkedList<Forma>();
        this.imagenes = new HashMap<String, Image>(16);
        margen=0;
    }

    public static Transformador getInstance(){
        return INSTANCE;
    }

    // Procesamiento de nivel

    // Aqui no importa el fondo, ese esta en actualizar vista
    public void transformarNivel() {
        ajustarMargen();
        for(final Plataforma p : Acotador.getInstance().acotarNivel()){
        
            Forma plataforma = new Forma() {
                Image imagen = relacionaImagen(p);

                Point posicion = new Point((p.getPosicion().x*ANCHO), 600-(p.getPosicion().y*ALTO)-imagen.getHeight(null));

                public Point getPosicion() {
                    return posicion;
                }

                public BufferedImage getImage() {
                    return (BufferedImage)imagen;
                }

                public double getZ() {
                    return 0d;
                }

                public void setPosicion(int x, int y) {
                    throw new UnsupportedOperationException("Not supported yet.");
                }
            };
            p.setTamanio((int)(ANCHO*p.getAncho())-10, (int)(ALTO*p.getAlto())-5);
            p.setLocacion(new Point((int)(p.getPosicion().getX()*ANCHO), (p.getPosicion().y*ALTO)));
            formas.add(plataforma);
            
        }
        for(final Personaje p : Acotador.getInstance().nivel.getPersonajes()){

            Forma plataforma = new Forma() {

                Image imagen = relacionaImagen(p);

                Point posicion = new Point((p.getPosicion().x), 600-(p.getPosicion().y)-imagen.getHeight(Vista.getPanel()));

                public Point getPosicion() {
                    return posicion;
                }

                public BufferedImage getImage() {
                    return (BufferedImage)imagen;
                }

                public double getZ() {
                    return 0d;
                }

                public void setPosicion(int x, int y) {
                    throw new UnsupportedOperationException("Not supported yet.");
                }
            };
            
            formas.add(plataforma);
            
        }
    }

    public void actualizarVista() {
       formas.clear();
       LinkedList<Integer> yes = new LinkedList<Integer>();
       yes.add(0);
       yes.add(150);
       yes.add(165);
       hacerFondo(3, yes);
       formas.addAll(fondosL);
        transformarNivel();
        Vista.getInstance().getPanel().canvas1.mover(margen);
        Vista.getInstance().setFormas(formas);

    }

    public int getMargen() {
        return margen;
    }

    public void setMargen(int margen) {
        this.margen = margen;
    }

    // Metodos auxiliares

    private Image encuentraImagen(String imagen) {
        Image img = imagenes.get(imagen);
        if (img != null) return img;
        img = CreadorImagen.crearImagen(imagen);
        imagenes.put(imagen, img);
        return img;
    }

    /** Recibe el objeto a pintar y regresa la imagen */
    private Image relacionaImagen(Relacionable objeto) {
        return encuentraImagen(DiccionarioImagen.getRelacionado(objeto));
    }

    private void ajustarMargen() {
        if((margen%ANCHO)>ANCHO){
            Acotador.getInstance().setInicio(Acotador.getInstance().getInicio()+1);
        }
    }

    public void mover(int x){
        margen+=x;
    }

    public void hacerFondo(int numero, final LinkedList<Integer> y){
        if(fondosL==null){
            fondosL = new LinkedList<Forma>();
            for(int i=0;i<numero;i++){
                final int num = i;
                Forma f = new Forma() {

                    Image imagen = relacionaImagen(new Relacionable() {
                        public String getLlave() { return "fondo"+(num+1); }
                    });

                    Point posicion = new Point(0, y.get(num));

                    public Point getPosicion() {
                        return posicion;
                    }

                    public BufferedImage getImage() {
                        return (BufferedImage)imagen;
                    }

                    public double getZ() {
                        return 0d;
                    }

                    public void setPosicion(int x, int y) {
                        posicion.setLocation(x, y);
                    }
                };
                fondosL.add(f);
                Forma f2 = new Forma() {

                    Image imagen = relacionaImagen(new Relacionable() {
                        public String getLlave() { return "fondo"+(num+1); }
                    });

                    Point posicion = new Point(imagen.getWidth(null), y.get(num));

                    public Point getPosicion() {
                        return posicion;
                    }

                    public BufferedImage getImage() {
                        return (BufferedImage)imagen;
                    }

                    public double getZ() {
                        return 0d;
                    }

                    public void setPosicion(int x, int y) {
                        posicion.setLocation(x, y);
                    }
                };
                fondosL.add(f2);
            }
        }else{
            Acotador.getInstance().setInicio((int)(margen/ANCHO));
            //System.out.println ("Margen: " + margen);
            //System.out.println ("Ancho: " + ANCHO);
            for(int i=1;i<=numero*2;i+=2){
                int desfase = (int)(margen / (Math.pow(PARALAJE, (i+1)/2) ));
                Forma f1 = fondosL.get(i-1);
                Forma f2 = fondosL.get(i);
                int suma = 0;
                int anchoImagen = f1.getImage().getWidth();
                int avanzadoMono = (margen-desfase)/anchoImagen ;
                int avanzadoPaisaje = (int)(f1.getPosicion().getX()/anchoImagen);
                double avanzadoPaisajeD = f1.getPosicion().getX()/anchoImagen;
                f1.setPosicion(avanzadoPaisaje * anchoImagen + desfase, f1.getPosicion().y);
                f2.setPosicion(avanzadoPaisaje * anchoImagen + desfase + anchoImagen, f2.getPosicion().y);
                if (avanzadoMono > avanzadoPaisajeD) {
                    f1.setPosicion((int)f2.getPosicion().getX(),f1.getPosicion().y);
                    f2.setPosicion((int)f1.getPosicion().getX() + anchoImagen, f2.getPosicion().y);
                }
                // int formula =(int)(margen/(64/Math.pow(2, (i-1)/2)));
                // System.out.println ("Formula: " + formula);

                
            }
        }
        
    }
}
